package dao

import (
	"errors"
	"fmt"
	"time"

	"github.com/ammyhaber/seckill/service/order/model"
	"github.com/jmoiron/sqlx"
)

// 定义错误常量
var (
	// 自定义错误
	ErrNoRows = errors.New("未找到记录")
)

// OrderDAO 订单数据访问对象
type OrderDAO struct {
	db *sqlx.DB
}

// NewOrderDAO 创建订单DAO
func NewOrderDAO(db *sqlx.DB) *OrderDAO {
	return &OrderDAO{db: db}
}

// 获取订单表名（分表策略：按用户ID哈希）
func getOrderTableName(userID int64) string {
	// 使用简单的哈希算法，将用户ID映射到8个分表之一
	tableIndex := userID % 8
	return fmt.Sprintf("order_%d", tableIndex)
}

// CreateOrder 创建订单
func (d *OrderDAO) CreateOrder(order *model.Order) error {
	// 获取表名
	tableName := getOrderTableName(order.UserID)

	// 构建SQL语句
	sqlQuery := fmt.Sprintf(`INSERT INTO %s 
		(id, user_id, product_id, product_name, product_price, quantity, total_amount, status, expire_time, created_at, updated_at) 
		VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, tableName)

	// 执行SQL
	_, err := d.db.Exec(sqlQuery,
		order.ID,
		order.UserID,
		order.ProductID,
		order.ProductName,
		order.ProductPrice,
		order.Quantity,
		order.TotalAmount,
		order.Status,
		order.ExpireTime,
		order.CreatedAt,
		order.UpdatedAt,
	)

	return err
}

// GetOrderByID 根据订单ID和用户ID获取订单
func (d *OrderDAO) GetOrderByID(orderID, userID int64) (*model.Order, error) {
	// 获取表名
	tableName := getOrderTableName(userID)

	// 构建SQL语句
	sqlQuery := fmt.Sprintf("SELECT * FROM %s WHERE id = ? AND user_id = ?", tableName)

	// 查询订单
	var order model.Order
	err := d.db.Get(&order, sqlQuery, orderID, userID)
	if err != nil {
		// 检查错误消息，判断是否为"未找到记录"的情况
		if err.Error() == "sql: no rows in result set" {
			return nil, nil
		}
		return nil, err
	}

	return &order, nil
}

// UpdateOrderStatus 更新订单状态
func (d *OrderDAO) UpdateOrderStatus(orderID, userID int64, status model.OrderStatus) error {
	// 获取表名
	tableName := getOrderTableName(userID)

	// 构建SQL语句
	sqlQuery := fmt.Sprintf("UPDATE %s SET status = ?, updated_at = ? WHERE id = ? AND user_id = ?", tableName)

	// 执行SQL
	_, err := d.db.Exec(sqlQuery, status, time.Now(), orderID, userID)
	return err
}

// PayOrder 支付订单
func (d *OrderDAO) PayOrder(orderID, userID int64) error {
	// 获取表名
	tableName := getOrderTableName(userID)

	// 构建SQL语句
	sqlQuery := fmt.Sprintf("UPDATE %s SET status = ?, pay_time = ?, updated_at = ? WHERE id = ? AND user_id = ? AND status = ?", tableName)

	// 执行SQL
	payTime := time.Now()
	result, err := d.db.Exec(sqlQuery, model.OrderStatusPaid, payTime, payTime, orderID, userID, model.OrderStatusPending)
	if err != nil {
		return err
	}

	// 检查是否有记录被更新
	affected, err := result.RowsAffected()
	if err != nil {
		return err
	}

	if affected == 0 {
		return errors.New("订单不存在或状态不正确")
	}

	return nil
}

// CancelOrder 取消订单
func (d *OrderDAO) CancelOrder(orderID, userID int64) error {
	// 获取表名
	tableName := getOrderTableName(userID)

	// 构建SQL语句
	sqlQuery := fmt.Sprintf("UPDATE %s SET status = ?, updated_at = ? WHERE id = ? AND user_id = ? AND status = ?", tableName)

	// 执行SQL
	result, err := d.db.Exec(sqlQuery, model.OrderStatusCanceled, time.Now(), orderID, userID, model.OrderStatusPending)
	if err != nil {
		return err
	}

	// 检查是否有记录被更新
	affected, err := result.RowsAffected()
	if err != nil {
		return err
	}

	if affected == 0 {
		return errors.New("订单不存在或状态不正确")
	}

	return nil
}

// GetExpiredOrders 获取过期未支付的订单
func (d *OrderDAO) GetExpiredOrders() ([]*model.Order, error) {
	// 由于订单分表，需要查询所有分表
	var allExpiredOrders []*model.Order

	for i := 0; i < 8; i++ {
		tableName := fmt.Sprintf("order_%d", i)
		sqlQuery := fmt.Sprintf("SELECT * FROM %s WHERE status = ? AND expire_time < ?", tableName)

		var orders []*model.Order
		err := d.db.Select(&orders, sqlQuery, model.OrderStatusPending, time.Now())
		if err != nil {
			return nil, err
		}

		allExpiredOrders = append(allExpiredOrders, orders...)
	}

	return allExpiredOrders, nil
}

// GetOrdersByUserID 获取用户的订单列表
func (d *OrderDAO) GetOrdersByUserID(userID int64, status *model.OrderStatus) ([]*model.Order, error) {
	// 获取表名
	tableName := getOrderTableName(userID)

	// 构建SQL语句
	var sqlQuery string
	var args []interface{}

	if status != nil {
		sqlQuery = fmt.Sprintf("SELECT * FROM %s WHERE user_id = ? AND status = ? ORDER BY created_at DESC", tableName)
		args = []interface{}{userID, *status}
	} else {
		sqlQuery = fmt.Sprintf("SELECT * FROM %s WHERE user_id = ? ORDER BY created_at DESC", tableName)
		args = []interface{}{userID}
	}

	// 查询订单
	var orders []*model.Order
	err := d.db.Select(&orders, sqlQuery, args...)
	if err != nil {
		return nil, err
	}

	return orders, nil
}
